// Global variables
levelHeight = 7;		// starting at 1  (max = 15)
levelWidth = 7;		// sgtarting at 1  (max = 20)
tileSize = 32;

openList = new Array();		// the open list for A*
navPath = new Array();		// the finished path to follow
// There is no "closed" list.  
// 	I'm simplifying things by setting a "closed" flag within each node



// ----------------------------------------------------------------
// Functions

function aStar( startNode, endNode ){
	// Perform A*
	trace("");
	trace("   aStar( "+ startNode +", "+ endNode +" )");
	
	currentNode = startNode;
	calcNode( currentNode, currentNode.g );
	addToOpen( currentNode.id );
	while ( openList.length > 0  &&  currentNode != endNode ){
	//for ( loop = 0; loop < 13; loop++ ){		//DEBUG:	Loop a specified number of times
		closeNode(currentNode);
		calcAreaNodes( currentNode );
		currentNode = findOpenNode( "f", true );
		trace( "openList:  "+openList.toString() );
		trace("***  currentNode: "+currentNode);
		trace("***  endNode: "+endNode);
		trace("***  currentNode != endNode: ");
		trace(currentNode != endNode);
		trace("***  openList.length: "+openList.length);
		if (openList.length > 0  &&  currentNode != endNode){		trace("***  continue loop")		}else{		trace("***  STOP loop")		}
	//}		//end loop  (DEBUG)
	}		//end while
	
	if (currentNode == endNode){
		// path was found
		trace("path was found!");
		return true;	
	}else{	
		// no path found
		trace("path was NOT found!");
		return false;	
	}
}		//end function






function buildArray()
{
	trace("");
	trace("   buildArray()");
	idNum = 0;
	for (y=0; y< levelHeight; y++)
	{
		for (x=0; x< levelWidth; x++)
		{
			_root.attachMovie("node", "newNode", idNum);
			trace("created:   node" + idNum);
			newNode.g = -1;
			newNode.h = -1;
			newNode.f = -1;
			newNode.closed = false;
			newNode.opened = false;
			newNode.extraCost = 0;
			newNode.id = idNum;
			newNode.y = y;
			newNode.x = x;
			newNode._y = y * tileSize;
			newNode._x = x * tileSize;
			scale = tileSize * 100 / 16;
			newNode._xscale = scale;
			newNode._yscale = scale;
			
			for ( i in newNode ){
				trace(i + ":  " + newNode[i]);
			}
			
			newNode._name = "node" + idNum;
			idNum ++;
			trace("---------------------------");
		}		//end for x
	}		//end for y
}		//end function






function closeNode( node )
{
	trace("");
	trace("   closeNode( "+ node +" )");
	node.closed = true;
	node.gotoAndStop("closed");
	//search for value in openList
	for ( i in openList )
	{
		if ( openList[i] == node.id )
		{
			trace(node + " removed from openList");
			openList.splice( i, 1 );		// remove from openList
			trace("openList: " + openList.toString() );
		}		//end if
	}		//end for...in
}		//end function



function calcAreaNodes( parentNode ){
	trace("");
	trace("   calcAreaNodes( "+ parentNode +" )");
	for (  y = parentNode.y - 1;  y <= parentNode.y + 1;  y++  )
	{
		for (  x = parentNode.x - 1;  x <= parentNode.x + 1;  x++  )
		{
			if (  inBounds(x, y) )
			{
				childNode = xyGetNode(x, y);
				if (childNode.closed == false  &&  childNode.opened == false)
				{
					calcNode( childNode, parentNode.g );
					addToOpen( childNode.id );
				}
			}		//end if
		}		//end for x
	}		//end for y
}		//endFunction



function calcNode( thisNode, parentG )
{
	trace("");
	trace("   calcNode( "+ thisNode +", "+ parentG +" )");
	thisNode.g = 1 + thisNode.extraCost + parentG;
	thisNode.h = getDistance( thisNode, endNode );
	thisNode.f = thisNode.g + thisNode.h;
	trace("g: "+thisNode.g+"   (cost to reach this node)");
	trace("h: "+thisNode.h+"   (distance to destination)");
	trace("f: "+thisNode.f+"   (total cost)");
}		//end function



function findOpenNode( attrib, remove )
{
	trace("");
	trace("   findOpenNode( "+ attrib +" )");
	bestNode = IdGetNode( openList[0] );
	for ( index = 0;  index < openList.length;  index++ )
	{
		checkNode = IdGetNode( openList[index] );
		if ( checkNode[attrib] < bestNode[attrib] )
		{
			bestNode = checkNode;
		}		//end if [attrib]
	}		//end for index
	if ( remove == true )
	{
		openList.splice( index, 1 );		// removes this from the openList
	}
	trace("bestNode:  "+bestNode)
	return bestNode;
}		//end function



function findAreaNode( parentNode, attrib )
{
	trace("");
	trace("   findAreaNode( "+ parentNode +", "+ attrib +" )");
	bestNode = parentNode;
	for (  y = parentNode.y - 1;  y <= parentNode.y + 1;  y++  )
	{
		for (  x = parentNode.x - 1;  x <= parentNode.x + 1;  x++  )
		{
			if (  inBounds(x, y)  )
			{
				checkNode = xyGetNode(x, y);
				if ( checkNode.g != -1 )
				{
					if ( checkNode[attrib] < bestNode[attrib] )
					{
						bestNode = checkNode;
					}		//end if [attrib]
				}		//end if (g != -1)
			}		//end if
		}		//end for x
	}		//end for y
	trace("bestNode:  " + bestNode);
	return bestNode;
}//		end function



function getCoords( id )
{
	trace("");
	trace("   getCoords( "+ id +" )");
	y = Math.floor( id / levelWidth );
	x = id - ( levelWidth * y );
	trace("x:  " + x);
	trace("y:  " + y);
	_root.getCoords.x = x;
	_root.getCoords.y = y;
}		//end function



function addToOpen( id )
{
	trace("");
	trace("   addToOpen( "+ id +" )");
	openList.push( id );
	_root["node"+id].opened = true;
	_root["node"+id].gotoAndStop("open");
	trace("openList: " + openList.toString() );
}		//end function



function getDistance( nodeA, nodeB )
{
	trace("");
	trace("   getDistance( "+ nodeA +", "+ nodeB +" )");
	xDiff = nodeB.x - nodeA.x;
	trace("xDiff:  "+xDiff);
	yDiff = nodeB.y - nodeA.y;
	trace("yDiff:  "+yDiff);
	distance = Math.sqrt(xDiff*xDiff + yDiff*yDiff);
	trace("distance:  "+distance);
	return distance;
}		//end function



function xyGetNode( x, y )
{
	trace("");
	//trace("   xyGetNode( "+ x +", "+ y +" )");
	id = y * levelWidth;
	id += x;
	nam = "node" + id;
	trace("node:  "+_root[nam]);
	return _root[nam];
}		//end function



function inBounds( x, y ){
	trace("");
	//trace("   inBounds( "+ x +", "+ y +" )");
	inRange = true;
	if (x < 0) {						inRange = false;	}
	if (x >= levelWidth) {		inRange = false;	}
	if (y < 0) {						inRange = false;	}
	if (y >= levelHeight) {		inRange = false;	}
	trace("inRange: "+inRange);
	return inRange;
}		//end function



function IdGetNode( id ){
	trace("");
	//trace("   IdGetNode( "+ id +" )");
	nam = "node" + id;
	return _root[nam];
}		//end function



function buildPath(){
	trace("");
	trace("   buildPath()");
	currentNode = endNode;
	navPath.push( currentNode.id );
	trace("navPath: "+navPath.toString() );
	while( currentNode != startNode )
	{
		currentNode = findAreaNode( currentNode, "g" );
		navPath.push( currentNode.id );
		trace("navPath: "+navPath.toString());
	}		//end while
	navPath.reverse();
	trace(  navPath.toString()  );
}		//end function


